home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / os20 / cli / FrontPubScreen.lha / FrontPubScreen / FrontPubScreen.w < prev    next >
Encoding:
Text File  |  1992-04-13  |  9.6 KB  |  261 lines

  1. % CWEB source for FrontPubScreen
  2. % 12 Apr 1992 john fieber (jfieber@@sophia.smith.edu)
  3.  
  4. \nocon % omit table of contents
  5. \datethis % print date on listing
  6. \def\progname{\.{FrontPubScreen}}
  7.  
  8. @* FrontPubScreen. This program is for AmigaDOS 2.0 or later. It does
  9. one simple and useful thing when you are working with public screens:
  10. if the frontmost screen is a public screen, it returns the name of
  11. that screen.  Since the the front screen is generally the one you are
  12. working on, it effectively returns the name of the screen you are
  13. working on.
  14.  
  15. A good example of how this can be used is with a ``hotkey'' program
  16. for opening pop-up utilities, command shells, editors or whatever. To
  17. illustrate, in this CLI command: $$\hbox{\tt NewCLI
  18. CON:20/50/540/180/AmigaShell/AUTO/SCREEN`\progname`}$$
  19. \.{`\progname`} will be replaced by the output of \progname.  Since
  20. \progname\ displays the name of the front screen, the result the
  21. above command is a CLI window opening up on whatever screen you
  22. happen to be working on.  This command attached to a hot-key provides
  23. an instant CLI on whatever screen you happen to be working on.  Other
  24. programs that allow you to specify a screen to open on can use the
  25. same technique.  For TurboText users, try: $$\hbox{\tt ttx screen
  26. `progname`}$$ attached to a hotkey.
  27.  
  28. Unfortunately this nifty feature only works if the front screen is
  29. indeed a public screen.  Fortunately there are a growing number of
  30. programs that do open public screens.  Also, you can create your own
  31. using one of the various public screen managers roaming around the
  32. ``net''.
  33.  
  34. @ {\bf Copying.}  Feel free to copy and distribute this program but
  35. please don't distribute the executable without this source code.
  36. Also, feel free to make changes but please make and document the
  37. changes in a cweb change file, not the original.  Also, I encourage
  38. people who are writing little pop-up type applications to stick this
  39. little bit of code in.  Public screens are nifty things so use them
  40. and make them useful!
  41.  
  42. If you do make a change file, use the code in your own program, or
  43. otherwise find this program useful I would like to hear about it.
  44. Send email to John Fieber at \.{jfieber@@sophia.smith.edu}.
  45.  
  46. @ Okay, enough description, now on to the program, starting with a
  47. little thing to teach \.{cweave} about one of the special Amiga
  48. types\dots
  49.  
  50. @f ULONG int
  51.  
  52. @ All good AmigaDOS programs should have string such as the following
  53. embedded somewhere in the program.  The CLI command \.{Version} will
  54. look for this string and display it if found.  This approach is much
  55. easier than writing in code to provide a command line switch and to
  56. display the version and much more consistant from the user's point of
  57. view.
  58.  
  59. @c
  60. char version[] = "\0$VER: FrontPubScreen 1.0 (4.12.92)";
  61.  
  62. @ Here is the general layout of the program.  We first check the
  63. value of |argc| to determine if the program was run from a command
  64. shell or from the Workbench.  If |argc == 0| then \progname\ was
  65. started from the Workbench. Since it has no useful function in that
  66. context, we just exit.  If |argc >= 1| then we move on and try the
  67. name of a useful public screen.
  68.  
  69. @c
  70. @<Include files@>@;
  71.  
  72. @<Function prototypes@>@;
  73.  
  74. @<Global variables@>@;
  75.  
  76. main(argc, argv)
  77. int argc;
  78. char *argv[];
  79. {
  80.     if (argc) {
  81.         @<Open system libraries@>;
  82.         @<Get screen name@>;
  83.         @<Output screen name@>;
  84.         @<Close system libraries@>@;
  85.     }
  86. }
  87.  
  88. @ We don't really need to include the extra baggage of \.{stdio.h}
  89. either during compilation or linking since AmigaDOS provides for
  90. writing things out to the console. But we {\it do\/} need to include
  91. the headers to get at those system functions.
  92.  
  93. @<Include files@>=
  94. #include <exec/types.h>
  95. #include <intuition/intuition.h>
  96. #include <intuition/intuitionbase.h>
  97. #include <dos/dos.h>
  98.  
  99. @ We also want to include the the Commodore function prototypes to be
  100. ANSI compliant and the \#{\bf pragma}'s to bypass the library access
  101. functions in \.{amiga.lib} that make the code unnecessairly large and
  102. slow.
  103.  
  104. @<Function prototypes@>=
  105.  
  106. #include <proto/intuition.h>
  107. #include <proto/dos.h>
  108. #include <proto/exec.h>
  109.  
  110.  
  111. @ The variable |IntuitionBase| is a pointer to base address of the
  112. Intuition Library.  The value returned by the |OpenLibrary()| call
  113. will be placed here. Also needed is a place to store the name of the
  114. public screen that the program will return.  The value for
  115. |MAXPUBSCREENNAME| is defined in \.{screens.h} (which is included
  116. with \.{intuition.h}). Finally, we have a pointer to a screen
  117. structure.
  118.  
  119. @<Global variables@>=
  120.  
  121. struct IntuitionBase *IntuitionBase;
  122. char public_screen_name[MAXPUBSCREENNAME];
  123. struct Screen *public_screen_address;
  124.  
  125. @ Now we must open the Intuition library so we can get at the nifty
  126. system functions for twiddling with screens. If the call to
  127. |OpenLibrary()| fails, it will return |NULL|.  We must exit
  128. gracefully in the event that this occurs.
  129.  
  130. Notice that since Intuition has its own non-standard library
  131. structure we must typecast the |OpenLibrary()| function which by
  132. definition returns a pointer to a standard library structure.
  133.  
  134. @<Open system libraries@>=
  135.  
  136. IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",36L);
  137. if (!IntuitionBase) {
  138.     exit(20L);
  139. }
  140.  
  141. @ To clean up at the end of the program, the Intuition library must
  142. be closed.  Again since Intuition has a non-standard library structure
  143. we need to typecast it so that the use of |CloseLibrary()| matches
  144. its definition.
  145.  
  146. @<Close system libraries@>=
  147.  
  148. CloseLibrary((struct Library *) IntuitionBase);
  149.  
  150. @ Moving right along, here is the code that prints out the
  151. (hopefully) useful information regarding a public screen name.  The
  152. variable |public_screen_name| is assumed to contain the screen name
  153. of the front public screen, or the default public screen.  Just to
  154. check its validity, we try to lock the screen.  In the event that
  155. fails we just return \.{Workbench} which should always work in some
  156. way shape or form.
  157.  
  158. @<Output screen name@>=
  159.  
  160. public_screen_address = LockPubScreen(public_screen_name);
  161. if (public_screen_address) {
  162.     (void) PutStr(public_screen_name);
  163.     (void) PutStr("\n");
  164.     UnlockPubScreen(NULL, public_screen_address);
  165. }
  166. else {
  167.     (void) PutStr("Workbench\n");
  168. }
  169.  
  170. @ Now we must figure out some useful information for the previous
  171. section to display.  A couple more variables must be defined to aid in the
  172. search for the name of the front public screen.
  173.  
  174. @<Global variables@>=
  175.  
  176. ULONG intuition_lock;
  177. struct Screen *front_screen_address;
  178. struct List *public_screen_list;
  179. struct PubScreenNode *public_screen_node;
  180.  
  181. @ The address of the front screen is easily found in the
  182. |IntuitionBase| structure.  However, since this is a system structure
  183. that we are not normally at liberty to examine, we must first get
  184. permission from Intuition to examine it.  This is accomplished with
  185. the |LockIBase()| function which sets up a semaphore.  This is much
  186. friendlier than simply locking the whole system with |forbid()|
  187. and |permit()| while we look at the structure.
  188.  
  189. With the address of the frontmost screen in hand, we check to see if
  190. it is a public or Workbench screen.  If so, we search the public
  191. screen list for a match.  The variable |public_screen_name| is set to
  192. a |NULL| string at the start and then checked at the end.  If it is
  193. still |NULL|, then the front screen was not found in the public
  194. screen list so we ask the system for the name of the default public
  195. screen.
  196.  
  197. @<Get screen name@>=
  198.  
  199. public_screen_name[0] = '\0';
  200.  
  201. intuition_lock = LockIBase(0L);
  202. front_screen_address = IntuitionBase->FirstScreen;
  203. if ((front_screen_address->Flags & PUBLICSCREEN) || (front_screen_address->Flags & WBENCHSCREEN)) {
  204.     UnlockIBase(intuition_lock);
  205.     @<Search public screen list@>;
  206. }
  207. else {
  208.     UnlockIBase(intuition_lock);
  209. }
  210.  
  211. if (public_screen_name[0] == '\0') {
  212.     GetDefaultPubScreen(public_screen_name);
  213. }
  214.  
  215.  
  216. @ Here we lock the public screen list and examine it
  217. looking for a match to |front_screen_address|.  If one is found,
  218. we then copy the name of the screen into |public_screen_name| for
  219. later use. Note that the AutoDocs mention that the screen pointer in
  220. the |PubScreenNode| structure is not trustworthy. However, in this
  221. case nothing catastrophic will happen though if it is wrong---the
  222. program won't work right but it should not affect anything else.
  223.  
  224. @<Search public screen list@>=
  225.  
  226. public_screen_list = LockPubScreenList();
  227. public_screen_node = (struct PubScreenNode *) public_screen_list->lh_Head;
  228. while (public_screen_node) {
  229.     if (public_screen_node->psn_Screen == front_screen_address) {
  230.         strcpy(public_screen_name, public_screen_node->psn_Node.ln_Name);
  231.         break;
  232.     }
  233.     public_screen_node = (struct PubScreenNode *) public_screen_node->psn_Node.ln_Succ;
  234. }
  235. UnlockPubScreenList();
  236.  
  237. @ And thus we are finished!
  238.  
  239. @ {\bf Other notes.} There are still a few problems that hopefully
  240. won't be too problematic.  Basically, although a public screen may be
  241. available when \progname\ runs, there is no guarantee that it will
  242. still be around later when that screen is used by whatever
  243. called \progname.  In order to ensure this we would have to maintain
  244. a lock on the screen until the caller has locked the screen, either
  245. with |LockPubScreen()| or by having a window open on it.
  246.  
  247. To do this properly would require communication between the
  248. applications so you might as well just build the \progname\ right
  249. in and not bother with this silly utility.  Alternately
  250. \progname\ could start another process to hold the lock for a
  251. while and possibly monitor the visitor count on the screen.  This
  252. might help but the payoff would probably be much smaller than the
  253. effort involved to implement it.
  254.  
  255. Also, if the comments and explainations of this program seem a bit
  256. excessive it is because I'm just learning how to use this nifty
  257. invention of D.~Knuth called \.{CWEB}.
  258. \medskip\rightline{--john fieber}
  259.  
  260. @* Index.
  261.